/**
C++ STL 和常用数据结构测试
*/

#include <iostream>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <unordered_map>
#include <utility>

using namespace std;

int main(int argc, char* argv[]) {
    /*
    unordered map
    */
    // 默认构造
    unordered_map<int, int> map1;
    // 表示声明多大的 map
    unordered_map<int, int> map2(3);
    // 构造并直接初始化
    // {} 本质是 initializer_list 右值，可被隐式转换成匹配的类型
    unordered_map<int, int> map3 = {{1, 2}, {3, 2}};
    map3.insert(pair<int, int>(4, 5));
    // 构造并直接复制
    unordered_map<int, int> map4 = map3;
    // map 插入，类似正常语言操作，就是通过 {k, v} 这种
    // 返回值是 pair 时，可以直接拆分
    {
        auto [iterator, ok] = map3.insert({1, 1});
        if (ok) {
            cout << "map3 inserted: {" << iterator->first << ", "
                 << iterator->second << "}" << endl;
        } else {
            cout << "map3 insert failed, already exists: {" << iterator->first
                 << ", " << iterator->second << "}" << endl;
        }
    }
    // erase 删除对应键
    // 返回有多少个元素被删除
    {
        auto iterator = map3.erase(5);
        if (iterator == 0) {
            cout << "map3 key 5 not present" << endl;
        } else {
            cout << "map3 key 5 delete " << iterator << " pair" << endl;
        }
    }
    // 重写了 operator[]，可以通过 [] 键直接访问元素
    // 也可以通过 at 获取，但若没有会掷出错误
    // 视情况选择：
    // operator[]：键不存在时自动插入
    // at()：键不存在时抛出 std::out_of_range 异常
    cout << "key 3 in map3 is: " << map3[3] << endl;
    try {
        cout << map3.at(10) << endl;
    } catch (std::out_of_range& e) {
        // what() -> what operation causes the exception
        cout << "map3 index 10 out of range: " << e.what() << endl;
    }

    /*
    pair / tuple 测试
    C++ 中，pair 是二元组，其值的索引可直接使用 first / second
    tuple 是多元组，可容纳多个不同类型的元素，是泛化的 pair
    */
    pair<int, int> p1 = {1, 2};
    tuple<int, int, int> t1 = {1, 2, 3};
    // tuple 取元素操作为 get<index>(tuple)
    // 也可以通过 auto [x, y, z] = tuple 这样操作
    cout << "tuple index 0: " << get<0>(t1) << endl;
    auto [t11, t12, t13] = t1;
}